#include "auth.h"
#include "database.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstring>

Auth::Auth(Database* db) : db_(db) {}

Auth::~Auth() = default;

std::optional<User> Auth::authenticate(const std::string& username, const std::string& password) {
    std::cout << "Authenticating user: '" << username << "' with password: '" << password << "'" << std::endl;

    std::string escapedUsername = db_->escapeString(username);
    std::string sql = "SELECT id, username, password, role FROM users WHERE username = '" + escapedUsername + "'";

    auto result = db_->query(sql);
    if (!result) {
        std::cout << "Database query failed" << std::endl;
        return std::nullopt;
    }

    MYSQL_ROW row = mysql_fetch_row(result.get());
    if (!row) {
        std::cout << "User not found in database" << std::endl;
        return std::nullopt;
    }

    std::string storedPassword = row[2];
    std::cout << "Found user: id=" << row[0] << ", username='" << row[1] << "', stored_password='" << storedPassword << "', role='" << row[3] << "'" << std::endl;

    bool passwordValid = verifyPassword(password, storedPassword);
    std::cout << "Password verification: " << (passwordValid ? "SUCCESS" : "FAILED") << std::endl;

    if (passwordValid) {
        User user;
        user.id = std::stoi(row[0]);
        user.username = row[1];
        user.role = row[3];
        return user;
    }

    return std::nullopt;
}

bool Auth::userExists(const std::string& username) {
    std::string escapedUsername = db_->escapeString(username);
    std::string sql = "SELECT COUNT(*) FROM users WHERE username = '" + escapedUsername + "'";

    auto result = db_->query(sql);
    if (!result) {
        return false;
    }

    MYSQL_ROW row = mysql_fetch_row(result.get());
    if (!row) {
        return false;
    }

    return std::stoi(row[0]) > 0;
}

bool Auth::verifyPassword(const std::string& password, const std::string& storedPassword) {
    // 暂时使用明文比较，生产环境应该使用哈希
    return password == storedPassword;
}

std::string Auth::hashPassword(const std::string& password) {
    // 生产环境应该使用bcrypt或Argon2
    return simpleHash(password);
}

std::string Auth::simpleHash(const std::string& input) {
    std::string result;
    unsigned long hash = 5381;

    for (char c : input) {
        hash = ((hash << 5) + hash) + c; // hash * 33 + c
    }

    std::stringstream ss;
    ss << std::hex << hash;
    result = ss.str();

    // 填充到32位
    while (result.length() < 32) {
        result = "0" + result;
    }

    return result.substr(0, 32);
}
